AOP(aspect-orient-programming)本质是一种自动插桩。它可以批量化在指定位置插入用户指定的代码(如特定method运行前后)。AOP解决的痛点是实际应用中为了保证安全性等原因,会在业务代码之外加入大量重复的,与业务代码关联性不强的代码。如安全检查或日志等。AOP实现了程序员只需要在语言中提供建议(advise),就可以让编译器自动插入这些代码。

AOP分为静态AOP和动态AOP。静态AOP速度最快,但每次调整都需要重新编译,AspectJ/AspectC是典型的静态AOP。动态AOP存在运行时开销,但是简单。

Spring框架采用动态AOP。是通过java proxy实现的。

java proxy是一个类,其作用是生成一个特定类型对象的包装proxy对象。接口完全一样,但是调用proxy对象的接口会先被捕获,可以在执行原接口前后执行其他代码。

在Java中,动态代理是一种常用的设计模式,它允许你在不修改目标对象的前提下,通过创建一个代理对象来拦截对目标对象的方法调用。这通常用于实现诸如日志记录、事务管理、权限检查等功能,而不需要在每个业务逻辑类中重复相同的代码。

下面是一个简单的Java动态代理示例,使用了Java自带的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。这个例子中,我们定义了一个简单的接口和它的实现类,并创建了一个处理程序来拦截对这个接口的所有方法调用。

首先,我们需要定义一个接口:

public interface MyService {
    void doSomething();
}

然后,实现这个接口:

public class MyServiceImpl implements MyService {
    @Override
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

接下来,创建一个InvocationHandler实现类来处理所有的方法调用:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method call");
        Object result = method.invoke(target, args);
        System.out.println("After method call");
        return result;
    }
}

最后,使用Proxy类创建一个动态代理对象,并调用其方法:

import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        // 实例化真实对象
        MyService realObject = new MyServiceImpl();

        // 创建InvocationHandler实例
        InvocationHandler handler = new MyInvocationHandler(realObject);

        // 通过Proxy.newProxyInstance创建代理对象
        MyService proxyObject = (MyService) Proxy.newProxyInstance(
                MyService.class.getClassLoader(),
                new Class[]{MyService.class},
                handler);

        // 调用代理对象的方法
        proxyObject.doSomething();
    }
}

这段代码中,MyService是服务接口,MyServiceImpl是该接口的具体实现。MyInvocationHandler实现了InvocationHandler接口,并且在其invoke方法中添加了一些额外的操作(比如打印日志)。最后,在Main类中,我们通过Proxy.newProxyInstance方法创建了一个代理对象,并通过这个代理对象调用了doSomething方法。在这个过程中,invoke方法会被调用,从而执行我们在MyInvocationHandler中定义的额外操作。